/*
Copyright (C) 2016  Marien Raat

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "carExhaust.h"
#include "config.h"

#include <cmath>
#include <iostream>

CarExhaust::CarExhaust()
{
    boostParticlesNeeded = 0.0f;
    vertices.setPrimitiveType(sf::Quads);
}

void CarExhaust::update(sf::Vector2f position, sf::Vector2f velocity,
                        float angle, float boostUsed)
{
    addBoostParticles(position, velocity, angle, boostUsed);
    updateParticles();
}

void CarExhaust::draw(sf::RenderTarget &target,
                      sf::RenderStates states) const
{
    states.texture = texture;

    target.draw(vertices, states);
}

void CarExhaust::addBoostParticles(sf::Vector2f position,
                                   sf::Vector2f velocity,
                                   float angle,
                                   float boostUsed)
{
    for (boostParticlesNeeded += 5000.0f * boostUsed * timeStep;
         boostParticlesNeeded > 0; boostParticlesNeeded -= 1.0f) {
        particles.push_back(Particle());
        int i = particles.size() - 1;

        particles[i].position = position +
            ROTATE_VECTOR2(
                sf::Vector2f((rand() % 10000) / 400.0f - 12.5f,
                             (rand() % 10000) / 400.0f - 12.5f),
                angle);

        float speed = 0.0f + ((rand() % 10000) / 100.0f);
        float pAngle = angle + ((rand() % 2) ? 1.0f : -1.0f) *
            90 * DEG_TO_RAD;
        sf::Vector2f direction(cos(pAngle), sin(pAngle));
        float shootSpeed = 10.0f + ((rand() % 10000) / 100.0f);
        particles[i].velocity = speed * direction +
            shootSpeed * sf::Vector2f(cos(angle), sin(angle));

        particles[i].size = sf::Vector2f
            (1.0f + sqrt((rand() % 6400) / 20.0f),
             0.5f + sqrt((rand() % 6400) / 50.0f));

        particles[i].rotation = angle;

        particles[i].lifetimeLeft = 0.3f + ((rand() % 200) / 2000.0f);
        particles[i].lifetime = (0.4f + particles[i].lifetimeLeft) /
            2.0f;
    }
}

void CarExhaust::updateParticles()
{
    vertices.resize(4 * particles.size());
    for (int i = 0; i < particles.size(); i++) {
        particles[i].position += particles[i].velocity * timeStep;
        particles[i].lifetimeLeft -= timeStep;

        vertices[4 * i + 0].position = particles[i].position +
            ROTATE_VECTOR2(
                sf::Vector2f(-particles[i].size.x / 2,
                             -particles[i].size.y / 2)
                , particles[i].rotation);
        vertices[4 * i + 1].position = particles[i].position +
            ROTATE_VECTOR2(
                sf::Vector2f(particles[i].size.x / 2,
                             -particles[i].size.y / 2)
                    , particles[i].rotation);
        vertices[4 * i + 2].position = particles[i].position +
            ROTATE_VECTOR2(
                sf::Vector2f(particles[i].size.x / 2,
                             particles[i].size.y / 2)
                , particles[i].rotation);
        vertices[4 * i + 3].position = particles[i].position +
            ROTATE_VECTOR2(
                sf::Vector2f(-particles[i].size.x / 2,
                             particles[i].size.y / 2)
                , particles[i].rotation);

                vertices[4 * i + 0].texCoords = sf::Vector2f(64, 0);
                vertices[4 * i + 1].texCoords = sf::Vector2f(0, 0);
                vertices[4 * i + 2].texCoords = sf::Vector2f(0, 64);
                vertices[4 * i + 3].texCoords = sf::Vector2f(64, 64);

        for (int j = 0; j < 4; j++)
            vertices[4 * i + j].color = getBoostParticleColor
                (std::max(0.0f, (particles[i].lifetimeLeft /
                                 particles[i].lifetime)));
    }
    for (int i = 0; i < particles.size(); i++) {
        if (particles[i].lifetimeLeft < 0.0f) {
            particles.erase(particles.begin() + i);
            i--;
        }

    }
}

sf::Color CarExhaust::getBoostParticleColor(float ratio)
{
    return sf::Color(255,
                     255.0f * std::max(0.0f, ratio - 0.1f),
                     0,
                     (ratio > 0.75f ? 1.0f : ratio / 0.75f) *
                     255.0f);
}
